package shiro;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;

import java.util.*;

/**
 * 第三阶段拓展, 将用户的私密信息进行加密
 */
public class MyShiroTestNewRealmAddMD5 {

    public static void main(String[] args) {

        CustomRealm customerRealm = new CustomRealm();
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        // 创建加密
        HashedCredentialsMatcher hashedCredentialsMatcher=new HashedCredentialsMatcher();
        // 设置MD5加密
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        // 设置MD5加密次数
        hashedCredentialsMatcher.setHashIterations(1);
        // 设置加密机制到自定义的CustomRealm中
        customerRealm.setCredentialsMatcher(hashedCredentialsMatcher);;
        defaultSecurityManager.setRealm(customerRealm);
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");
        subject.login(token);
        System.out.println(subject.getPrincipal() + "是否验证成功" + subject.isAuthenticated());
        // 使用ArrayList存储角色
        List<String> roles = new ArrayList<String>();
        roles.add("admin");
        roles.add("adminplus");
        roles.add("adminpro");
        // 循环测试角色
        for (String role : roles) {
            System.out.println("当前用户是" + subject.getPrincipal() + "\t 是否具有" + role + "角色 \t" + subject.hasRole(role));
        }
        // 使用arraylist存放权限组
        List<String> permissions = new ArrayList<String>();
        permissions.add("update");
        permissions.add("delete");
        permissions.add("add");
        permissions.add("get");
        // 循环验证当前用户是否具有对应的权限
        for (String permission : permissions) {
            System.out.println("当前用户是" + subject.getPrincipal() + "\t 是否具有" + permission + "权限 \t"
                    + subject.isPermitted(permission));
        }
        System.out.println(subject.isPermitted("get"));
        // 登出当前用户
        subject.logout();
        // 验证当前用户是否登出
        System.out.println(subject.getPrincipal() + "是否登录成功?" + subject.isAuthenticated());
    }


    /**
     * 创建自定义的Realm集成AuthorizingRealm
     * 重写doGetAuthenticationInfo方法表示我们需要进行认证的过程
     */
    static class CustomRealm extends AuthorizingRealm {
        // 模拟数据库存放用户名和密码
        Map<String, String> userMap = new HashMap<String, String>();

        {
            userMap.put("zhangsan", "b0b7919f13cc024fce6b4ff7cb9bef43");
            userMap.put("lisiplus", "b0b7919f13cc024fce6b4ff7cb9bef43");
            super.setName("CustomerRealm");
        }

        // 模拟数据库存放的角色名
        Map<String, String> roles = new HashMap<String, String>();

        {
            roles.put("zhangsan", "admin");
            roles.put("lilsiplus", "adminpro");
        }

        // 模拟数据库存放的权限名
        Map<String, String> permissions = new HashMap<String, String>();

        {
            permissions.put("admin", "update");
            permissions.put("admin", "delete");
            permissions.put("adminpro", "update");
            permissions.put("adminpro", "add");
        }

        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            // TODO Auto-generated method stub

            String userName = (String) principals.getPrimaryPrincipal();
            Set<String> roles = getRolesByUsername(userName);
            Set<String> permissions = getPermissionsByUserName(userName);

            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            simpleAuthorizationInfo.setRoles(roles);
            simpleAuthorizationInfo.setStringPermissions(permissions);
            return simpleAuthorizationInfo;
        }

        private Set<String> getPermissionsByUserName(String userName) {
            // TODO Auto-generated method stub
            Set<String> permissions = new HashSet<String>();
            permissions.add("delete");
            permissions.add("update");
            return permissions;
        }

        private Set<String> getRolesByUsername(String userName) {
            // TODO Auto-generated method stub
            Set<String> roles = new HashSet<String>();
            roles.add("admin");
            roles.add("test");
            return roles;
        }

        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            // TODO Auto-generated method stub

            // 从subject客体中取得当前用户名
            String userName = (String) authenticationToken.getPrincipal();
            // 模拟从数据库取得当前用户名对应的密码
            String password = getPasswordByUsername(userName);
            if (password == null) {
                return null;
            }
            // 取的当前认证的信息
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userName, password, "CustomerRealm");
            simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("hashyanzhi"));
            return simpleAuthenticationInfo;
        }

        private String getPasswordByUsername(String userName) {
            return userMap.get(userName);
        }
    }
}
